#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <stdexcept>

/**
 * @brief 读取文件中指定字节偏移量范围内的内容。
 * * @param filename 要读取的文件名。
 * @param start_offset 起始字节偏移量（从 0 开始计数）。
 * @param end_offset 结束字节偏移量（该位置的字节不包含在结果中）。
 * @return std::string 读取到的文件内容块。如果失败则返回空字符串。
 */
std::string read_file_chunk(const std::string& filename, 
                            std::streamoff start_offset, 
                            std::streamoff end_offset) {
    
    // 1. 基本校验
    if (start_offset < 0 || end_offset < 0 || start_offset >= end_offset) {
        std::cerr << "错误: 偏移量参数无效 (start_offset 必须小于 end_offset 且都非负)." << std::endl;
        return "";
    }

    // 2. 打开文件
    // 使用 std::ios::binary 保证字节级精确性
    std::ifstream is(filename, std::ios::in | std::ios::binary); 
    
    if (!is.is_open()) {
        std::cerr << "错误: 无法打开文件: " << filename << std::endl;
        return "";
    }

    // 3. 计算需要读取的长度
    // 长度 = 结束位置 - 起始位置
    std::streamoff length = end_offset - start_offset;
    
    // 4. 定位 (Seek Get)
    // 总是建议在定位前清理流状态，尽管刚打开时通常是干净的
    is.clear(); 
    is.seekg(start_offset, std::ios::beg);

    if (is.fail()) {
        std::cerr << "错误: 定位到起始偏移量失败。" << std::endl;
        is.close();
        return "";
    }

    // 5. 准备缓冲区并读取
    // 创建一个足够大的vector作为缓冲区
    std::vector<char> buffer(length);
    
    // 从当前光标位置开始，读取 length 个字节到缓冲区
    is.read(buffer.data(), length);

    // 6. 检查实际读取的字节数
    // is.gcount() 返回上一次无格式读取操作（即 read()）实际读取的字符数。
    std::streamsize bytes_read = is.gcount();

    // 7. 关闭文件
    is.close();

    // 8. 返回结果
    if (bytes_read > 0) {
        // 使用实际读取到的字节数来构建 std::string
        return std::string(buffer.begin(), buffer.begin() + bytes_read);
    } else {
        // 如果 bytes_read 为 0，表示没有读到内容（例如 start_offset 太大）
        std::cerr << "警告: 未读取到任何内容。" << std::endl;
        return "";
    }
}

int main(){
    std::string result;
    result = read_file_chunk("../corpus/page_library.dat", 11, 1080);
    std::cout << result << std::endl;

    std::cout << "---------------" << std::endl;

    result = read_file_chunk("../corpus/page_library.dat", 1080, 2175);
    std::cout << result << std::endl;

    std::cout << "---------------" << std::endl;

    result = read_file_chunk("../corpus/page_library.dat", 2175, 8900);
    std::cout << result << std::endl;

    return 0;
}